package com.my.okhttps.test.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadFactoryBuilder;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ejlchina.okhttps.HttpResult;
import com.ejlchina.okhttps.OkHttps;
import com.my.core.domain.exception.ServiceException;
import com.my.okhttps.test.service.ISheBaoService;
import com.my.okhttps.test.vo.SheBaoCanBaoVo;
import com.my.okhttps.test.vo.SheBaoJiaoFeiVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.*;

/**
 * 社保对接
 * @author timo 2020/12/14
 */
@Service
@Slf4j
public class SheBaoServiceImpl implements ISheBaoService {
    /**社保标签*/
    public static final String SHEBAO_TAR = "SHEBAO";
    public static final String BASE = "/yhbcp-engine/rest";
    /**领卡查询 */
    public static final String GET_CARD = BASE + "/INT_Ecard_001";
    /**签发*/
    public static final String SIGN = BASE + "/INT_Ecard_002";
    /**回调参数解析*/
    public static final String CALL_BACK_PARSE = BASE + "/INT_Ecard_003";
    /**社保接口*/
    public static final String SHEBAO = BASE +"/INT_Ecard_004";
    /**
     * SpringBoot获取当前环境代码,Spring获取当前环境代码
     */
//    @Value("${spring.profiles.active}")
//    private String profiles;
//    public static String devUrl = "http://218.88.215.93:10018/zwfw-cloud/shebao/dianzishebaoka/callBack?1=1";
//    public static String previewUrl = "http://218.88.215.93:10024/zwfw-cloud/shebao/dianzishebaoka/callBack?1=1";
//    public static String proUrl = "https://zwapi.lzjczl.com:8881/zwfw-cloud/shebao/dianzishebaoka/callBack?1=1";
//    public static final String DOMAIN = "http://10.4.68.10:6062";
//    public static final String DOMAIN = "http://218.88.215.90:9091";

    /**接口基础域名地址*/
    public static String DOMAIN;
    /**回调地址*/
    public static String location;
    /**加密key*/
    public static String publicKeyStr;

    @Value("${shebao.domain:}")
    public void setDOMAIN(String DOMAIN) {
        SheBaoServiceImpl.DOMAIN = DOMAIN;
    }
    @Value("${shebao.location:}")
    public void setLocation(String location) {
        SheBaoServiceImpl.location = location;
    }
    @Value("${shebao.publicKeyStr:}")
    public void setPublicKeyStr(String publicKeyStr) {
        SheBaoServiceImpl.publicKeyStr = publicKeyStr;
    }


    public JSONObject operation(Map<String,String> map, String url){
        HttpResult httpResult = OkHttps.sync(DOMAIN +url)
                .addUrlPara("biz_content", JSON.toJSONString(map))
                .addHeader("publicKeyStr", publicKeyStr)
                .skipSerialPreproc()
                .tag(SHEBAO_TAR)
                .post();
        HttpResult.Body body = httpResult.getBody();
        JSONObject jsonObject = JSON.parseObject(String.valueOf(body));
        String code = jsonObject.getString("code");
        if("1".equals(code)) {
            return jsonObject.getJSONObject("biz_data");
        }
        throw new ServiceException(jsonObject.toJSONString());
    }

    /**
     * 工伤缴费记录
     * @param gerenNo
     * @param startrow
     * @param endrow
     * @param type 1 失业 0工伤
     * @return
     */
    @Override
    public List<SheBaoJiaoFeiVo> getshebaoGongShangShiyeJiaoFei(String gerenNo, String startrow, String endrow, Integer type){
        Map<String, String> map = new HashMap<>();
        map.put("aac001", gerenNo);
        map.put("callCode", "I01020");
        if(type==0){
            map.put("jybh", "PRC-YTJ006");
        }else{
            map.put("jybh", "PRC-YTJ020");
        }
        map.put("startrow", StrUtil.isNotBlank(startrow)?startrow:"0");
        map.put("endrow", StrUtil.isNotBlank(endrow)?endrow:"10086");

        JSONObject bizData = operation(map, SHEBAO);
        String code = bizData.getString("code");
        if ("1".equals(code)) {
            JSONArray data = bizData.getJSONArray("data");
            Iterator<Object> iterator = data.iterator();
            List<SheBaoJiaoFeiVo> returnVos = new ArrayList<SheBaoJiaoFeiVo>();
            while (iterator.hasNext()) {
                SheBaoJiaoFeiVo sheBaoJiaoFeiVo = new SheBaoJiaoFeiVo();
                JSONObject next = (JSONObject) iterator.next();
                String date = next.getString("aae002");
                String jishu = next.getString("aic020");
                if(Integer.parseInt(jishu)<0){
                    continue;
                }
                sheBaoJiaoFeiVo.setDate(date);
                sheBaoJiaoFeiVo.setJiaofeijishu(jishu);
                String grjfje = next.getString("grjfje");
                sheBaoJiaoFeiVo.setGerenshijiao(grjfje);

                String dwjfje = next.getString("dwjfje");
                String aab004 = next.getString("aab004");
                sheBaoJiaoFeiVo.setDanweishijiao(dwjfje);
                sheBaoJiaoFeiVo.setJiaofeidanwei(aab004);
                returnVos.add(sheBaoJiaoFeiVo);
            }
            return returnVos;
        }
        throw new ServiceException(bizData.toJSONString());
    }
    /**
     * 社保养老缴费信息
     * @param chargeType 企业职工 机关事业单位 城乡居民
     * @param gerenNo
     * @param userStatus 在职 退休 机关在职退休不一样
     * @param startrow endrow 企业职工查询的开始条数和结束条数，可以为空
     * @return
     */
    @Override
    public List<SheBaoJiaoFeiVo> getshebaoYangLaoJiaoFei(String chargeType,String gerenNo,String userStatus,String startrow,String endrow){
        Map<String, String> map = new HashMap<>();
        map.put("aac001", gerenNo);
        map.put("callCode", "I01020");
        switch (chargeType){
            case "机关事业单位":
                map.put("jybh", "CX013-JG");
                if("在职".equals(userStatus)){
                    map.put("aae140", "120");
                }else{
                    map.put("aae140", "180");
                }
                String yyyy = DateUtil.format(new Date(), "yyyy");
                map.put("aae041", yyyy+ "01");
                map.put("aae042", yyyy+ "12");
                break;
            case "企业职工":
                map.put("jybh", "PRC-YTJ005");
                map.put("startrow", StrUtil.isNotBlank(startrow)?startrow:"0");
                map.put("endrow", StrUtil.isNotBlank(endrow)?endrow:"10086");
                break;
            case "城乡居民":
                map.put("jybh", "YTJ038");
                break;
            default:
        }
        JSONObject bizData = operation(map, SHEBAO);
        String code = bizData.getString("code");
        if("1".equals(code)){
            JSONArray data = bizData.getJSONArray("data");
            Iterator<Object> iterator = data.iterator();
            List<SheBaoJiaoFeiVo> returnVos = new ArrayList<SheBaoJiaoFeiVo>();
            while (iterator.hasNext()) {
                SheBaoJiaoFeiVo sheBaoJiaoFeiVo = new SheBaoJiaoFeiVo();
                JSONObject next = (JSONObject) iterator.next();
                String date = next.getString("aae002");
                String jishu = next.getString("aic020");
                if(Integer.parseInt(jishu)<0){
                    continue;
                }
                sheBaoJiaoFeiVo.setJiaofeijishu(jishu);
                String grjfje = next.getString("grjfje");
                sheBaoJiaoFeiVo.setGerenshijiao(grjfje);
                if(chargeType.equals("城乡居民")){
                    date = next.getString("aae001");
                    sheBaoJiaoFeiVo.setDanweishijiao("");
                    sheBaoJiaoFeiVo.setJiaofeidanwei("");

                    String yad002 = next.getString("yad002");
                    String yad001 = next.getString("yad001");
                    String aaa115 = next.getString("aaa115");
                    String dwjfrq = next.getString("dwjfrq");
                    sheBaoJiaoFeiVo.setCxjflx(aaa115);
                    sheBaoJiaoFeiVo.setCxzfbt(yad002);
                    sheBaoJiaoFeiVo.setCxzfdj(yad001);
                    sheBaoJiaoFeiVo.setCxdwjfrq(dwjfrq);
                }else{
                    String dwjfje = next.getString("dwjfje");
                    String aab004 = next.getString("aab004");
                    sheBaoJiaoFeiVo.setDanweishijiao(dwjfje);
                    sheBaoJiaoFeiVo.setJiaofeidanwei(aab004);
                }
                //养老补缴会出现的情况
                if("".equals(date) || date == null ){
                    sheBaoJiaoFeiVo.setDaozhangdate(next.getString("dwjfrq"));
                    sheBaoJiaoFeiVo.setGerenjiaofeihuarujine(next.getString("yic486"));
                    sheBaoJiaoFeiVo.setJiaofeileixing(next.getString("aae143"));
                }
                sheBaoJiaoFeiVo.setDate(date);
                returnVos.add(sheBaoJiaoFeiVo);
            }
            return returnVos;
        }

        throw new ServiceException(bizData.toJSONString());
    }


    class CallableCbxx implements Callable {
        SheBaoCanBaoVo cbxxZhengWu;
        CountDownLatch latch;
        String idCard;
        public CallableCbxx(SheBaoCanBaoVo cbxxZhengWu, CountDownLatch latch,String idCard) {
            this.cbxxZhengWu = cbxxZhengWu;
            this.latch = latch;
            this.idCard = idCard;
        }
        @Override
        public Object call() throws Exception {

            log.info("查询社保卡信息");
            //表示异步操作
            Map<String, String> map = new HashMap<>();
            map.put("aac002", idCard);
            //参保信息
            map.put("jybh", "cbxx");
            JSONObject bizData = operation(map, SHEBAO);
            String code = bizData.getString("code");
            if("1".equals(code)){
                JSONArray data = bizData.getJSONArray("data");
                Iterator<Object> iterator = data.iterator();

                cbxxZhengWu.setIdCard(idCard);
                while (iterator.hasNext()){
                    JSONObject next = (JSONObject) iterator.next();
                    String aac003 = next.getString("aac003");
                    String aac084 = next.getString("aac084");
                    String aae044 = next.getString("aae044");
                    String aac001 = next.getString("aac001");

                    String aae004 = next.getString("aab004");//机关机构名称

                    cbxxZhengWu.setUserName(aac003);
                    cbxxZhengWu.setGerenNo(aac001);

                    cbxxZhengWu.setUserStatus(aac084);
                    cbxxZhengWu.setOrgName(StrUtil.isNotBlank(aae044)?aae044:aae004);
                    String aae140 = next.getString("aae140");
                    String chargeStatus = next.getString("aac031");
                    switch (aae140){
                        case "企业养老":
                            cbxxZhengWu.setChargeType("企业职工");
                            cbxxZhengWu.setYlCbzt(chargeStatus);
                            break;
                        case "机关养老":
                            cbxxZhengWu.setChargeType("机关事业单位");
                            cbxxZhengWu.setYlCbzt(chargeStatus);
                            break;
                        case "120"://机关
                            chargeStatus = next.getString("aac031_desc");
                            cbxxZhengWu.setChargeType("机关事业单位");
                            cbxxZhengWu.setYlCbzt(chargeStatus);
                            break;
                        case "210"://机关
                            chargeStatus = next.getString("aac031_desc");
                            cbxxZhengWu.setSyCbzt(chargeStatus);
                            break;
                        case "410"://机关
                            chargeStatus = next.getString("aac031_desc");
                            cbxxZhengWu.setGsCbzt(chargeStatus);
                            break;
                        case "170":
                            chargeStatus = next.getString("aac031_desc");
                            cbxxZhengWu.setChargeType("城乡居民");
                            cbxxZhengWu.setYlCbzt(chargeStatus);
                            break;
                        case "工伤保险":
                            cbxxZhengWu.setGsCbzt(chargeStatus);
                            break;
                        case "失业保险":
                            cbxxZhengWu.setSyCbzt(chargeStatus);
                            break;
                        default:
                    }
                }
//                if(StrUtil.isNotBlank(cbxxZhengWu.getCardNO()) && StrUtil.isNotBlank(cbxxZhengWu.getUserName())){
//                    String s1 = getshebaoGrqy(cbxxZhengWu.getIdCard(), cbxxZhengWu.getUserName());
//                    if(StrUtil.isNotBlank(s1)){
//                        cbxxZhengWu.setMoney(s1);
//                    }
//                }
                log.info("查询社保卡完毕");
                latch.countDown();
                return null;
            }
            latch.countDown();
            return bizData.toJSONString();
//            throw new ServiceException(bizData.toJSONString());
        }
    }
    class CallableCbzz implements Callable {
        SheBaoCanBaoVo cbxxZhengWu;
        CountDownLatch latch;
        String idCard;
        public CallableCbzz(SheBaoCanBaoVo cbxxZhengWu, CountDownLatch latch,String idCard) {
            this.cbxxZhengWu = cbxxZhengWu;
            this.latch = latch;
            this.idCard = idCard;
        }
        @Override
        public Object call() throws Exception {
            log.info("查询参保状态");
            boolean ex = false;
            //表示异步操作
            String s = getshebaoCardStatus(idCard,ex);
            if(!ex){
                if(s!=null){
                    JSONObject o = JSON.parseObject(s);
                    String cardNO = o.getString("aaz500");
                    //                    String cardData = o.getString("aaz503");
                    String cardStatus = o.getString("aaz502");
                    String cardCity = o.getString("aab034");
                    cbxxZhengWu.setCardCity(cardCity);
                    cbxxZhengWu.setCardStatus(cardStatus);
                    cbxxZhengWu.setCardNO(cardNO);
                    latch.countDown();
                    return null;
                }
            }
            latch.countDown();
            return s;
        }
    }
    class CallableGrqy implements Callable {
        SheBaoCanBaoVo cbxxZhengWu;
        CountDownLatch latch;
        String idCard;
        String name;
        public CallableGrqy(SheBaoCanBaoVo cbxxZhengWu, CountDownLatch latch,String idCard,String name) {
            this.cbxxZhengWu = cbxxZhengWu;
            this.latch = latch;
            this.idCard = idCard;
            this.name = name;
        }
        @Override
        public Object call() throws Exception {
            log.info("查询个人权益信息");
            boolean ex = false;

            String s = getshebaoGrqy(idCard, name,ex);
            if(!ex){
                if(StrUtil.isNotBlank(s)){
                    cbxxZhengWu.setMoney(s);
                    latch.countDown();
                    return null;
                }
            }
            latch.countDown();
            return s;
        }
    }
    /**
     * 参保信息+缴费金额+社保卡状态
     * @param idCard
     * @return
     */
    @Override
    public SheBaoCanBaoVo getshebaoCbxx(String idCard,String name)  {
        StringBuffer exceptionMsg = new StringBuffer();
        SheBaoCanBaoVo cbxxZhengWu = new SheBaoCanBaoVo();
        CountDownLatch latch=new CountDownLatch(3);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 3, 60,
                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(9),
                new ThreadFactoryBuilder().setUncaughtExceptionHandler(new MyHandler(latch)).build());

        List<Callable<String>> callables = new ArrayList<>();
        callables.add(new CallableCbzz(cbxxZhengWu, latch, idCard));
        callables.add(new CallableCbxx(cbxxZhengWu, latch, idCard));
        callables.add(new CallableGrqy(cbxxZhengWu, latch, idCard,name));
        //获取到所有任务的处理结果
        List<Future<String>> futures = null;
        try {
            futures = executor.invokeAll(callables);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (Future<String> future:futures){
            try {
                String s = future.get();
                if(StrUtil.isNotBlank(s)){
                    exceptionMsg.append(s);
                }
            } catch (ExecutionException | InterruptedException e) {
                e.printStackTrace();
                executor.shutdown();  //关闭线程池
                throw new ServiceException(e.toString());
            }
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
            executor.shutdown();  //关闭线程池
            throw new ServiceException(e.getMessage());
        }
        executor.shutdown();  //关闭线程池
        if(exceptionMsg.length()>0){
            throw new ServiceException(exceptionMsg.toString());
        }
        return cbxxZhengWu;
    }
    class MyHandler implements Thread.UncaughtExceptionHandler {
        CountDownLatch latch;
        public MyHandler(CountDownLatch latch) {
            this.latch = latch;
        }
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            latch.countDown();
            log.error("社保基本信息查询异常----------------------------------------threadId = {}, threadName = {}, ex = {}", t.getId(), t.getName(), e.getMessage());
        }
    }
    /**
     * 社保卡状态查询
     * @param idCard
     * @return
     */
    public String getshebaoCardStatus(String idCard,boolean ex){
        Map<String, String> map = new HashMap<>();
        map.put("aac002", idCard);
        map.put("jybh", "zmzx-001");
        map.put("callCode", "I01002");
        JSONObject bizData = operation(map, SHEBAO);
        String code = bizData.getString("code");
        //对接系统返回的code
        code = bizData.getString("code");
        if("1".equals(code)){
            JSONArray data = bizData.getJSONArray("data");
            JSONObject o = (JSONObject) data.get(0);
            return o.toString();
        }
        ex = true;
        return bizData.toJSONString();
//        throw new ServiceException(bizData.toJSONString());
    }

    /**
     * 获取社保个人权益
     * @param aac002 社会保障号 == 身份证
//     * @param aae001 年度
//     * @param aab301 参保地行政区划代码 -- 对方默认
//     * @param aae140 参保险种 -- 对方传
//     * @param aaz002 业务序列号 -- 对方传
     * @param aac003 姓名
     * @return
     */
    public String getshebaoGrqy(String aac002,String aac003,boolean ex){
        Map<String, String> map = new HashMap<>();
        map.put("aac002", aac002);
        map.put("aae001", DateUtil.format(new Date(),"yyyy"));
        map.put("aab301", "510500");
        map.put("aac003", aac003);
        map.put("jybh", "grqy");
        JSONObject bizData = operation(map, SHEBAO);
        String code = bizData.getString("code");
        if("1".equals(code)){
            JSONArray data = bizData.getJSONArray("data");
//                String s = StringEscapeUtils.unescapeJavaScript(data.get(0).toString());
//                JSONObject o = JSON.parseObject(s);
            JSONObject o = (JSONObject) data.get(0);
            JSONObject o1 = (JSONObject) o.get("CbLists");
            JSONObject o2 = (JSONObject) o1.get("cbList");
            double aic022 = o2.getDouble("AIC022");
            return StrUtil.toString(aic022);
        }
        ex = true;
        if("400000".equals(code)){
            //没有
            return bizData.toJSONString();
        }
        return bizData.toJSONString();
    }

    /************************************************ 电子社保卡 ***********************************************************************/

    /**
     * 电子社保卡领卡查询
     * 返回的领卡地址里面有/ 要去掉访问才行， 不然会返回到签发
     * @param idCard
     * @param name
     * @param phone
     * @return
     */
    @Override
    public String getCard(String idCard,String name,String phone){
        Map<String, String> map = new HashMap<>();
        map.put("aac002", idCard);
        map.put("aac003", name);
        map.put("aac067", phone);
        map.put("location",location);
        JSONObject bizData = operation(map, GET_CARD);
        String code = bizData.getString("code");
        if("1".equals(code)){
            //直接拉起卡面
            JSONObject data = bizData.getJSONObject("data");
            String cs = data.getString("cs");
//                return  cs.replace("/", "");
            return cs;
        }
        if("2".equals(code)){
            //未签发
            return sign(idCard, name, phone);
        }
        if("-2".equals(code)){
            return  bizData.getString("msg");
        }
        //社保返回失败
        return bizData.toString();
    }

    /**
     * 电子社保卡签发
     * @param idCard
     * @param name
     * @param phone
     * @return
     */
    public String sign(String idCard,String name,String phone){
        Map<String, String> map = new HashMap<>();
        map.put("aac002", idCard);
        map.put("aac003", name);
        map.put("aac067", phone);
        map.put("location",location);
        JSONObject bizData = operation(map, SIGN);
        String code = bizData.getString("code");
        if("1".equals(code)){
            //拉起签发页面
            JSONObject data = bizData.getJSONObject("data");
            String cs = data.getString("cs");
//                return cs.replace("/", "");
            return cs;
        }
        //社保返回失败
        return bizData.toString();
    }

    /**
     * 电子社保卡回调
     * @param request
     * @return
     */
    @Override
    public String callBack(HttpServletRequest request){
        String security = request.getParameter("security");
        security = security.replace("+"," ");
        String aac002 = request.getParameter("aac002");
        String aac067 = request.getParameter("aac067");
        String aac003 = request.getParameter("aac003");

        Map<String, String> map = new HashMap<>();
        map.put("security", security);
        map.put("aac002", aac002);
        map.put("aac003", aac003);
        map.put("aac067", aac067);
        JSONObject bizData = operation(map, CALL_BACK_PARSE);
        String code = bizData.getString("code");
        if("21".equals(code) || "3".equals(code)){
            //返回我们的页面
            return "gohome";
        }
        if("0".equals(code)){
            //错误
            return bizData.toJSONString();
        }
        return getCard(aac002,aac003,aac067);
    }


}
